﻿/*
 * Copyright (c) 2011 Intelygenz <www.intelygenz.com>
 * All rights reserved.
 * 
 * BSD License
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Description:
 * 
 * 	This JavaScript library provides different client-side optimization techniques for front construction.
 * It is independent and compatible with any server-side technology: JAVA, PHP, Python, GOOGLE APP ENGINE, .NET...
 * 
 * Dependences:
 * 	JQuery 1.5+
 *
 * Download:
 * 	Last stable version: http://kore.googlecode.com/svn/trunk/js/kore.js
 * 
 *  Previous version can be found at: http://kore.googlecode.com/svn/trunk/js/kore-x.x.x.js
 *  E.g.:
 *  	http://kore.googlecode.com/svn/trunk/js/kore-0.1.3.js 
 * 
 * Creation date: 2011-12-15
 * 
 * [version] date -> authors
 * 		upd|fix|new|dep - description
 *
 * [0.1.3] 2012-01-02 -> angel.sanchez@intelygenz.com
 *		upd - kore.config.Environment is a Getter/Setter function (added p_env param)
 * [0.1.2] 2011-12-21 -> jonas.dacruz@intelygenz.com
 * 		upd - All logs only writes the environment
 * 		new - kore.event.RemoveListener(p_eventName, f_func) -> For remove listeners
 * 		upd - kore.event.AddListener(p_eventName, f_func) -> Add more than one time the same function it's forbidden
 * [0.1.1] 2011-12-15
 * 		new - First release
 *
 * */

var kore = ( typeof kore === "undefined" ) ? {} : kore;


/**
 * Packages
 */
kore.out = {};
kore.config = {};
kore.global = {};
kore.local = {};
kore.event = {};
kore.net = {};
kore.lang = {};
kore.ui = {};
kore.util = {};
kore.screen = {};

//kore
//
(function(){
	// private context
	//
	var _Version = "0.1.3";
	var _Name    = "kore";
	var _JqMinVer= 1.5;			// jQuery oldest version required

	// public interfaces
	//
	kore.Name = function (){
		return _Name + " v" + _Version + " ["+kore.config.Environment()+"]";
	};
	
	kore.JqMinVersion = function () { 
		return _JqMinVer; 
	};

})();

//kore.out
//
(function(){
	// private context
	//

	// public interfaces
	//
	kore.out.Debug = function (){
		if(window.console && window.console.debug && kore.config.LogOf("debug") ){
			window.console.debug("["+kore.config.Environment()+"]", arguments);
		}
	};
	kore.out.Warning = function (){
		if(window.console && window.console.warn && kore.config.LogOf("warning") ){
			window.console.warn("["+kore.config.Environment()+"]", arguments);
		}
	};
	kore.out.Error = function (){
		if(window.console && window.console.error && kore.config.LogOf("error") ){
			window.console.error("["+kore.config.Environment()+"]", arguments);
		}
	};

})();

//kore.config
//
(function(){
	// private context
	//
	var _Data = {}
	,	_Environment = null
	,	_Log = {"error":true}
	;

	// public interfaces
	//
	kore.config.Load = function (p_json){
		if ( p_json ) {
			_Data = p_json;

			kore.global.Load( _Data["global"] );

			if ( _Data["log"] ) {
				var logConfig = _Data["log"][kore.config.Environment()];
				var logs = logConfig.split(",");
				for ( var logType in logs ) {
					_Log[ $.trim(logs[logType]) ] = true;
				}
			}
			
			kore.local.Load( _Data["local"] );
		}
		return _Data;
	};
	
	kore.config.LogOf = function (p_type){
		return _Log[p_type];
	};

	kore.config.Environment = function (p_env) {
		if ( p_env ) {
			_Environment = p_env;
		}
		else {
			if ( !_Environment ) {
				_Environment = _Data["environment-default"];
				for (var p in _Data["environment"] ){
					if ( document.location.href.indexOf( p ) > -1 ) {
						_Environment = _Data["environment"][p];
						break;
					}
				}
				if ( !_Environment ) {
					_Environment = "pro";
				}
			}
			return _Environment;
		}
	};

})();

//kore.global
//
(function(){
	// private context
	//
	var _Global = {};

	// public interfaces
	//
	kore.global.Load = function (p_hash){
		$.extend(_Global, p_hash);
		return _Global;
	};

	kore.global.Data = function (p_label, p_value){
		if ( p_label && p_value ) {
			_Global[p_label] = p_value; 	
		}
		else if ( p_label ) {
			return _Global[p_label];
		}
		else {
			return _Global;
		}
	};

})();

//kore.local
//
(function(){
	// private context
	//
	var _Local = {};

	// public interfaces
	//
	kore.local.Load = function (p_hash){
		$.extend(_Local, p_hash);
		return _Local;
	};

	kore.local.Data = function (p_label, p_value){
		if ( p_label && p_value ) {
			_Local[p_label][kore.config.Environment()] = p_value; 	
		}
		else if ( p_label ) {
			return _Local[p_label][kore.config.Environment()];
		}
		else  {
			return _Local;
		}
	};

})();

// kore.event
//
(function(){

	// private context
	//

	// { eventName1 : [func1, func2, ...], eventName2 : ... } 
	var _Event = {};

	function _FindListener(p_eventName, f_func){
		var events = _Event[p_eventName];
		if ( events ) {
			for ( var f=0, F=events.length; f<F; f++ ) {
				if ( events[f] === f_func ) {
					return f;
				}
			}
		}
		return -1;
	}

	function _AddListener(p_eventName, f_func){
		if ( !_Event[p_eventName] ) {
			_Event[p_eventName] = [];
		}

		var index = _FindListener( p_eventName, f_func );
		if ( index==-1 ) {
			index = _Event[p_eventName].length;
		}

		_Event[p_eventName][index] = f_func;

	};

	function _RemoveListener(p_eventName, f_func){
		var index = _FindListener(p_eventName, f_func);
		if ( index!=-1 ){
			_Event[p_eventName].splice(index,1);
		}
	};

	function _Dispatch(p_eventName, p_data){
		if ( _Event[p_eventName] ) {
			var funcs = _Event[p_eventName];
			for ( var f=0, F=funcs.length; f<F; f++ ) {
				funcs[f](p_data);
			}
		}
	};

	// public interfaces
	//
	kore.event.CURRENT_SCREEN_HIDE = "kore_current_screen_hide";

	kore.event.AddListener = function (p_eventName, f_func){
		_AddListener(p_eventName, f_func);
	};

	kore.event.RemoveListener = function (p_eventName, f_func){
		_RemoveListener(p_eventName, f_func);
	};
	
	kore.event.Dispatch = function (p_eventName, p_data){
		_Dispatch(p_eventName, p_data);
	};

})();


//kore.net
//
(function(){

	// private context
	//
	var _BaseUri = "";

	// public interfaces
	//
	kore.net.BaseUri = function (p_baseUri){
		if ( p_baseUri ) {
			_BaseUri = p_baseUri;
		}
		return _BaseUri;
	};

})();

//kore.lang
//
(function(){

	// private context
	//
	var _Locale = {};
	var _Data = {};

	function _Load(p_locale, p_data){
		_Locale = p_locale;
		_Data[_Locale] = p_data;
	};

	function _Get(p_label, p_locale){
		var locale = ( p_locale ) ? p_locale : _Locale;
		var value  = _Data[locale][p_label];
		if ( !value ) value = "??" + p_label + "??";
		return value;
	};

	function _Parse(p_html){
		var html = p_html;
		var matches = html.match(/@@[A-Z_\.]+@@/g);
		if ( matches ) {
			var f, F = matches.length;
			for ( f=0; f<F; f++ ) {
				html = html.replace(matches[f], _Get(matches[f].substring(2,matches[f].length-2)));
			}
		}
		return html;
	};

	// public interfaces
	//
	kore.lang.Load = function (p_locale, p_data){
		kore.out.Debug("[kore.ui.Load]", p_locale, p_data);
		
		return _Load(p_locale, p_data);
	};

	kore.lang.LoadFrom = function (p_locale, p_uri){
		kore.out.Debug("[kore.ui.LoadFrom]", p_locale, p_uri);
		
		$.ajax(
			{ url: p_uri
			, dataType: "json"
			, async: false
			, cache: true
			, success : 
				function (p_data){
					_Load(p_locale, p_data);
				}
			, error : 
				function (p_err) {
				
					var msg = "Error loading lang file";
					if ( p_err.status === 200 ) {
						msg = "Not valid JSON lang file";
					}
					else if ( p_err.status === 404 ) {
						msg = "Lang file not found";
					}
					kore.out.Err(p_err.status, msg, p_uri);
				}
			}
		);
	};

	kore.lang.Parse = function (p_html){
		return _Parse(p_html);
	};
	
	kore.lang.Get = function (p_label, p_locale) {
		return _Get(p_label, p_locale);
	};

})();

//kore.ui
//
(function(){

	// private context
	//
	function _HashToDom(p_hash, p_dom, p_filter){
		if ( p_filter ){
			var filter;
			for ( var f=0, F=p_filter.length; f<F; f++ ){
				filter = p_hash[p_filter[f]];
				if ( filter ) {
					p_dom.setAttribute(p_filter[f], filter);
				}
			}
		}
		else {
			for ( var label in p_hash){
				p_dom.setAttribute(label, p_hash[label]);
			}
		}
		return p_dom;
	}

	function _DomToHash(p_dom) {
		var hash = {};
		var attrs = p_dom.attributes;
		var label;
		for( var f=0, F=attrs.length; f<F; f++ ) {
			label = attrs[f].name;
			if ( label.indexOf("_")==0 ){
				label = label.substr(1);
			}
			hash[label] = attrs[f].value;
		}
		return hash;
	}

	function _Template(p_id){
		var $tmpl = $( "<div>"+kore.lang.Parse( document.getElementById(p_id).innerHTML )+"</div>" );
		return {
			 $Get : function (p_id) {
				 if ( p_id ) {
					 return $tmpl.find("[_id=" + p_id + "]");
				 }
				 return $tmpl.children();
			}
			,To : function (p_$container) {
				p_$container.replaceWith( $tmpl );
			}
		};
	}

	var _Loaded  = {};
	var _Loading = {};

	function _Include(p_ui) {
		var cssUri  = kore.net.BaseUri() + p_ui + ".css";
		var htmlUri = kore.net.BaseUri() + p_ui + ".html";
		
		kore.out.Debug("[kore.ui.Include]", cssUri, htmlUri);
		
		if ( !_Loaded[p_ui] && !_Loading[p_ui] ) {
			_Loading[p_ui] = htmlUri;
			if (document.createStyleSheet) {
	            document.createStyleSheet(cssUri);
	        }
	        else {
	            $("head").append($("<link rel='stylesheet' href='"+cssUri+"' type='text/css' />"));
	        }

			$.ajax(
				{ url: htmlUri
				, dataType: "html"
				, async: false
				, cache: true
				, success : 
					function (p_html){
						$("head").append( p_html );
						_Loaded[p_ui] = htmlUri;
					}
				, error : 
					function (p_err) {
						_Loading[p_ui] = null;
						
						var msg = "Error loading file";
						if ( p_err.status === 200 ) {
							msg = "Not valid HTML/CSS file";
						}
						else if ( p_err.status === 404 ) {
							msg = "File not found";
						}
						kore.out.Err(p_err.status, msg, htmlUri);
					}
				}
			);
		}
	}
	
	// public interfaces
	//
	kore.ui.Template = function (p_id){
		return _Template(p_id); 
	};

	kore.ui.Include = function (p_uiNames){
		kore.out.Debug("[kore.ui.Include]", p_uiNames);
		
		if ( typeof p_uiNames === "object" ) {
			for ( var i in p_uiNames ){
				_Include( p_uiNames[i] );
			}
		}
		else {
			_Include( p_uiNames );
		}
	};

	kore.ui.DomToHash = function (p_dom, p_hash){
		return _DomToHash(p_dom, p_hash);
	};

	kore.ui.HashToDom = function (p_hash, p_dom, p_filter){
		return _HashToDom(p_hash, p_dom, p_filter);
	};

})();

//kore.util
//
(function(){


})();


//kore.screen
//
(function(){
	// private context
	//
	var  _Screen = {}
		,_CurrentScreen = null
	;
	
	kore.event.AddListener(kore.event.CURRENT_SCREEN_HIDE, _OnCurrentScreenHide);
	
	function _OnCurrentScreenHide (p_params) {
		_CurrentScreen.Show( p_params );
	}
	
	// public interfaces
	//
	kore.screen.Add = function (p_screenId, p_instance) {
		kore.out.Debug("[kore.screen.Add]", p_screenId, p_instance);
		
		_Screen[p_screenId] = p_instance;
	};
	
	kore.screen.Goto = function (p_screenId, p_params) {
		kore.out.Debug("[kore.screen.Goto]", p_screenId, p_params);
		
		if ( !_Screen.hasOwnProperty(p_screenId) ) {
			kore.out.Err( "[kore.screen.Goto] kore.screen.Add() has to be previosly called", p_screenId );
		}
		else {
			var oldCurrentScreen = _CurrentScreen;
			_CurrentScreen = _Screen[p_screenId];

			if ( oldCurrentScreen != null ) {
				oldCurrentScreen.Hide();
			}
			else {
				_OnCurrentScreenHide();
			}
		}
	};

})();


// config autoload
//
(function () {
	if( typeof jQuery === "undefined" ) {
		kore.out.Err( "jQuery " + kore.JqMinVersion() + "+ previous load required" );
	}
	else if ( $().jquery < kore.JqMinVersion() ) {
		kore.out.Err( "jQuery " + $().jquery + " currently loaded, jQuery " + bbva.front.JqMinVersion() + "+ required" );
	}

	var base = document.getElementsByTagName("base");
	if ( base.length > 0 ) {
		base = base[0].attributes["href"].value;
	}
	else {
		base = "/";
	}
	baseUri = document.location.protocol + "//" + document.location.host + base;

	kore.net.BaseUri( baseUri );

	var configUri = baseUri + "js/kore.config.js"; // config file name
	
	kore.out.Debug("[Autoload kore.config.js] Loading...", configUri);
	
	$.ajax(
		{ url: configUri
		, dataType: "json"
		, async: false
		, cache: true
		, success : 
			function (p_json){
				kore.config.Load(p_json);
				kore.out.Debug("[Autoload kore.config.js] Config loaded", p_json);
			}
		, error : 
			function (p_err) {
				var msg = "Error loading config file";
				if ( p_err.status === 200 ) {
					msg = "Not valid JSON config file";
				}
				else if ( p_err.status === 404 ) {
					msg = "Config file not found";
				}
				kore.out.Err(p_err.status, msg, configUri);
			}
		}
	);
})();
